class Test 
{
	public m_world:Box2D.Dynamics.b2World;
	public m_bomb:Box2D.Dynamics.b2Body;
	public m_mouseJoint:Box2D.Dynamics.Joints.b2MouseJoint;
	public m_velocityIterations:number = 10;
	public m_positionIterations:number = 10;
	public m_timeStep:number = 1.0 / 30.0;
	public m_physScale:number = 30;
	//world mouse postion;
	public static mouseXWorldPhys:number;
	public static mouseYWorldPhys:number;
	public static mouseXWorld:number;
	public static mouseYWorld:number;
	//debugDraw;
	public m_sprite:DebugDraw;
	//public m_stage:egret.Stage;

	private mousePVec:Box2D.Common.Math.b2Vec2 = new Box2D.Common.Math.b2Vec2();

	public constructor(sprite:DebugDraw) 
	{
		this.m_sprite = sprite;

		let worldAABB:Box2D.Collision.b2AABB = new Box2D.Collision.b2AABB();
		worldAABB.lowerBound.Set(-1000, -1000);
		worldAABB.upperBound.Set(1000, 1000);
		
		let gravity:Box2D.Common.Math.b2Vec2 = new Box2D.Common.Math.b2Vec2(0.0, 10.0);
		let doSleep:boolean = true;

		this.m_world = new Box2D.Dynamics.b2World(gravity, doSleep);
		//this.m_world.SetBroadPhase(new Box2D.Dynamics.)
		this.m_world.SetWarmStarting(true);

		let dbgDraw:Box2D.Dynamics.b2DebugDraw = new Box2D.Dynamics.b2DebugDraw();
		dbgDraw.SetSprite(this.m_sprite.graphics);
		dbgDraw.SetDrawScale(this.m_physScale);
		dbgDraw.SetFillAlpha(0.3);
		dbgDraw.SetLineThickness(2.0);
		dbgDraw.SetFlags(Box2D.Dynamics.b2DebugDraw.e_shapeBit | 
						 Box2D.Dynamics.b2DebugDraw.e_jointBit);
		this.m_world.SetDebugDraw(dbgDraw);

		//create border of boxes;
		let wall:Box2D.Collision.Shapes.b2PolygonShape = new Box2D.Collision.Shapes.b2PolygonShape();
		let wallBd:Box2D.Dynamics.b2BodyDef = new Box2D.Dynamics.b2BodyDef();
		let wallB:Box2D.Dynamics.b2Body;

		//left
		wallBd.position.Set(-95 / this.m_physScale, 360 / this.m_physScale / 2);
		wall.SetAsBox(100/this.m_physScale, 400/ this.m_physScale / 2);
		wallB = this.m_world.CreateBody(wallBd);
		wallB.CreateFixture2(wall);

		//right
		wallBd.position.Set((640 + 95) / this.m_physScale, 360 / this.m_physScale / 2);
		wallB = this.m_world.CreateBody(wallBd);
		wallB.CreateFixture2(wall);
		//top
		wallBd.position.Set((640) / this.m_physScale / 2, -95 / this.m_physScale);
		wall.SetAsBox(680/this.m_physScale / 2, 100/ this.m_physScale);
		wallB = this.m_world.CreateBody(wallBd);
		wallB.CreateFixture2(wall);
		// //bottom
		wallBd.position.Set((640) / this.m_physScale  / 2, (360  + 95)/ this.m_physScale);
		wallB = this.m_world.CreateBody(wallBd);
		wallB.CreateFixture2(wall);

		if(this.m_sprite.graphics.parent)
		{
			var stage:PIXI.Container = this.m_sprite.graphics.parent;
			stage.on("mousedown",this.onTouchEvent,this);
			stage.on("mousemove",this.onTouchEvent,this);
			stage.on("mouseup",this.onTouchEvent,this);
		}
		/*
		if(this.m_sprite.stage)
		{
			this.m_sprite.stage.addEventListener(egret.TouchEvent.TOUCH_BEGIN, this.onTouchEvent,this);
			this.m_sprite.stage.addEventListener(egret.TouchEvent.TOUCH_END, this.onTouchEvent,this);
			this.m_sprite.stage.addEventListener(egret.TouchEvent.TOUCH_MOVE, this.onTouchEvent,this);
		}
		*/
	}
	///*
	private onTouchEvent(e:PIXI.interaction.InteractionEvent):void
	{
		
		Input.mouseX = e.data.global.x - this.m_sprite.graphics.x;
		Input.mouseY = e.data.global.y - this.m_sprite.graphics.y;
		
		switch(e.type)
		{
			case "mousedown":
				Input.mouseDown = true;
				break;
			case "mouseup":
				Input.mouseDown = false;
				break;
			case "mousemove":
				break;
		}
		//console.log("aaa",Input.mouseDown, Input.mouseX, Input.mouseY);
	}
	//*/
	public update():void
	{
		this.updateMouseWorld();
		this.mouseDestroy();
		this.mouseDrag();
		
		// let physStart:number = egret.getTimer();
		
		this.m_world.Step(this.m_timeStep, this.m_velocityIterations, this.m_positionIterations);
		this.m_world.ClearForces();

		this.m_world.DrawDebugData();

	}

	public updateMouseWorld():void
	{
		Test.mouseXWorldPhys = Input.mouseX / this.m_physScale;
		Test.mouseYWorldPhys = Input.mouseY / this.m_physScale;

		Test.mouseXWorld = Input.mouseX;
		Test.mouseYWorld = Input.mouseY;
	}

	public mouseDrag():void
	{
		//mouse press
		if(Input.mouseDown && !this.m_mouseJoint)
		{
			let body:Box2D.Dynamics.b2Body = this.getBodyAtMouse();

			if(body)
			{
				let md:Box2D.Dynamics.Joints.b2MouseJointDef = new Box2D.Dynamics.Joints.b2MouseJointDef();
				md.bodyA = this.m_world.GetGroundBody();
				md.bodyB = body;
				
				md.target.Set(Test.mouseXWorldPhys, Test.mouseYWorldPhys);
				md.collideConnected =true;
				md.maxForce = 300 * body.GetMass();
				this.m_mouseJoint = <Box2D.Dynamics.Joints.b2MouseJoint>this.m_world.CreateJoint(md);
				body.SetAwake(true);
			}
		}

		//mouse release
		if(!Input.mouseDown)
		{
			if(this.m_mouseJoint)
			{
				this.m_world.DestroyJoint(this.m_mouseJoint);
				this.m_mouseJoint = null;
			}
		}

		//mosue move
		if(this.m_mouseJoint)
		{
			let p2:Box2D.Common.Math.b2Vec2 = new Box2D.Common.Math.b2Vec2(Test.mouseXWorldPhys, Test.mouseYWorldPhys);
			this.m_mouseJoint.SetTarget(p2);
		}
	}

	public mouseDestroy():void
	{
		if(!Input.mouseDown && Input.isKeyPress(68/*D */))
		{
			let body:Box2D.Dynamics.b2Body = this.getBodyAtMouse(true);
			if(body)
			{
				this.m_world.DestroyBody(body);
				return;
			}
		}
	}

	public getBodyAtMouse(includeStatic:boolean = false):Box2D.Dynamics.b2Body
	{
		this.mousePVec.Set(Test.mouseXWorldPhys, Test.mouseYWorldPhys);
		let aabb:Box2D.Collision.b2AABB = new Box2D.Collision.b2AABB();
		aabb.lowerBound.Set(Test.mouseXWorldPhys - 0.001, Test.mouseYWorldPhys - 0.001);
		aabb.upperBound.Set(Test.mouseXWorldPhys + 0.001, Test.mouseYWorldPhys + 0.001);
		var body:Box2D.Dynamics.b2Body = null;
		var fixture:Box2D.Dynamics.b2Fixture;

		let self = this;
		function getBodyCallback(fixture:Box2D.Dynamics.b2Fixture):boolean
		{
			let shape:Box2D.Collision.Shapes.b2Shape = fixture.GetShape();
			if(fixture.GetBody().GetType() != Box2D.Dynamics.b2Body.b2_staticBody ||
			   includeStatic)
			{
				let inside:boolean = shape.TestPoint(fixture.GetBody().GetTransform(), self.mousePVec);
				if(inside)
				{
					body = fixture.GetBody();
					return false;
				}
			}
			return true;
		}
		this.m_world.QueryAABB(getBodyCallback, aabb);
		return body;
	}
}